package com.simple.common.framework.retrofit;

import com.google.common.base.Preconditions;
import com.simple.common.framework.context.Contexts;
import lombok.SneakyThrows;
import okhttp3.ResponseBody;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;
import retrofit2.Call;
import retrofit2.Response;

import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author yasud
 * @date 2021年03月02日 17:42
 * @description
 */
public class ExecuteUtils {

    /**
     * 执行接口
     *
     * @param call
     * @return
     */
    @SneakyThrows
    public static Map<String, Object> execute(Call<ResponseBody> call) {
        Tuple2<String, String> t
                = executeStringResultWithMediaType(call);
        Preconditions.checkState(t.getT1().contains(MediaType.APPLICATION_JSON_VALUE) ||
                t.getT1().contains(MediaType.TEXT_PLAIN_VALUE) ||
                t.getT1().contains(MediaType.TEXT_HTML_VALUE), t.getT2());
        String t2 = t.getT2();
        Map map = Contexts.OBJECTMAPPER.readValue(t2, Map.class);
        return map;
    }

    @SneakyThrows
    public static String executeStringResult(Call<ResponseBody> call) {
        Tuple2<String, String> t
                = executeStringResultWithMediaType(call);
        return t.getT2();
    }

    @SneakyThrows
    public static Tuple2<String, String> executeStringResultWithMediaType(Call<ResponseBody> call) {
        if (Objects.nonNull(call) && !call.isCanceled() && !call.isExecuted()) {
            Response<ResponseBody> execute = call.execute();
            String type = execute.headers().get(HttpHeaders.CONTENT_TYPE);
            if (StringUtils.isBlank(type)) {
                type = MediaType.TEXT_PLAIN_VALUE;
            }
            if (execute.isSuccessful()) {
                return Tuples.of(type, execute.body().string());
            } else {
                return Tuples.of(type, execute.errorBody().string());
            }
        }
        Preconditions.checkState(false, "执行失败");
        return null;
    }

    @SneakyThrows
    public static List<Map<String, Object>> executeArrayResult(Call<ResponseBody> call) {
        Tuple2<String, String> t
                = executeStringResultWithMediaType(call);
        Preconditions.checkState(t.getT1().contains(MediaType.APPLICATION_JSON_VALUE), t.getT2());
        String t2 = t.getT2();
        List list = Contexts.OBJECTMAPPER.readValue(t2, List.class);
        return list;
    }
}
